
package lk;

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;

import com.sun.corba.se.spi.ior.MakeImmutable;


public class DifferentDataSet {

	ArrayList<Employee> allEmployeeList = new ArrayList<Employee>();
	ArrayList<Employee> employeeList = new ArrayList<Employee>();
	ArrayList<Employee> noRequestEmployees = new ArrayList<Employee>();
	ArrayList<Employee> moreThan5AndNoRequestEmployees = new ArrayList<Employee>();
	CountingHashMap locations   = new CountingHashMap();
	CountingHashMap reservedLocations   = new CountingHashMap();
	
	BasicEmployee employees[];
	Integer[] locationArray;
	ArrayList<BasicEmployee> noChoiceEmployee = new ArrayList<BasicEmployee>();
	int employeeCount;	
	Connection con = null;
	public final static int NO_LOCATION_REQUESTED = -2;
	public final static int LOCATION_NOT_IN_VACANCY_LIST = -1;
	
	public final static int REQUEST_1 = 1;
	public final static int REQUEST_2 = 2;
	public final static int REQUEST_3 = 3;
	public final static int CURRENT_LOCATION = 0;
	public final static int NO_LOCATION = 4;
	
	String dbTable = "TRANSFERS_PMAS_1";
	
	public static void main(String[] args) {
		DifferentDataSet m = new DifferentDataSet();
		m.getSol();
		//m.printOldSolutionStats();
	}	
	
	public void printOldSolutionStats(){
		loadAllEmployees();
		finOldAssignmentScore();
	}
	
	public void getSol() {
		loadAndFilterEmployeeData();
		filterEmployees();
		convertToLightWeightDataStructures();
		printEmployess();
		printLocations();
	    Integer[] assignments = new Integer[employees.length];
	    long tStart = System.currentTimeMillis();
		//Integer[] a = findSolution(assignments, locationArray, 0);	
		//checkMamximumTransfers();
	    //checkBackEveryReqWithAboveEmployeesWithOneDownPenalty();		
		naiveMethod();  //Naive implementation
		//checkBackEveryReqWithAboveEmployees(); // Goes back and find a location from the above employees 
		//checkWeightForTransfers(); // This is where most request 1 's satsified
		//getMaximumLocation();
		//algorithmMaximumRequest1();
		String witeString = convertEmployeeDataToString();
		writeToFile(witeString, "/home/araaya/dev/Nuwan/Algo/Results/FinalResult.txt");
	}
	
	public void loadAllEmployees(){
		 ResultSet rs =null;
		try {
			con = DriverManager.getConnection("jdbc:mysql://localhost:3306/testing?useUnicode=true&characterEncoding=utf-8",
			          "root", "root");
			if (!con.isClosed()) {
               System.out.println("Successfully connected to reading Database ");
               Statement readStmt = (Statement) con.createStatement();
               String sql = "select * from GOV_TRANSFER.TRANSFERS_PMAS_1";
                             
               rs = readStmt.executeQuery(sql);
           	if (rs != null){
           		int count =0;
           		while (rs.next()) {
     			      String employeeNo = rs.getString("employeeNo");
     			      int currentServicePeriod = rs.getInt("currentServicePeriod");
     			      int totalServicePeriod = rs.getInt("totalServicePeriod");
     			      int currentLocationServicePeriod = rs.getInt("currentPlaceServicePeriod");
     			      String request1 = rs.getString("request1").trim();
     			      String request2 = rs.getString("request2").trim();
     			      String request3 = rs.getString("request3").trim();
     			      String currentLocation = rs.getString("currentLocation").trim();
     			      String oldAssignment = rs.getString("finalTansferResult").trim();
     			      //Employee e = new Employee(employeeNo, currentServicePeriod, totalServicePeriod, currentLocationServicePeriod, request1.trim(), request2.trim(), request3.trim(),currentLocation.trim());
     			      Employee e = new Employee(employeeNo, currentServicePeriod, totalServicePeriod, currentLocationServicePeriod, request1.trim(),
     			    		  					request2.trim(), request3.trim(), currentLocation.trim(), oldAssignment);
     			      //employees[count] = e;
     			     /* if (count == 5){
     			    	 break; 
     			      }*/
     			     employeeList.add(e);
     	       		}
           	}
           	Collections.sort(employeeList);	     	
           }
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
	}

	public void loadAndFilterEmployeeData(){
		 ResultSet rs =null;
		try {
			con = DriverManager.getConnection("jdbc:mysql://localhost:3306/testing?useUnicode=true&characterEncoding=utf-8",
			          "root", "root");
			if (!con.isClosed()) {
                System.out.println("Successfully connected to reading Database ");
                Statement readStmt = (Statement) con.createStatement();
                String sql = "select * from GOV_TRANSFER."+dbTable;
                              
                rs = readStmt.executeQuery(sql);
            	if (rs != null){
            		int count =0;
            		while (rs.next()) {
      			      String employeeNo = rs.getString("employeeNo");
      			      int currentServicePeriod = rs.getInt("currentServicePeriod");
      			      int totalServicePeriod = rs.getInt("totalServicePeriod");
      			      int currentLocationServicePeriod = rs.getInt("currentPlaceServicePeriod");
      			      String request1 = rs.getString("request1").trim();
      			      String request2 = rs.getString("request2").trim();
      			      String request3 = rs.getString("request3").trim();
      			      String currentLocation = rs.getString("currentLocation").trim();
      			      String oldAssignment = rs.getString("finalTansferResult").trim();
      			      //Employee e = new Employee(employeeNo, currentServicePeriod, totalServicePeriod, currentLocationServicePeriod, request1.trim(), request2.trim(), request3.trim(),currentLocation.trim());
      			      Employee e = new Employee(employeeNo, currentServicePeriod, totalServicePeriod, currentLocationServicePeriod, request1.trim(),
      			    		  					request2.trim(), request3.trim(), currentLocation.trim(), oldAssignment);
      			      //employees[count] = e;
      			   /*   if (count == 5){
      			    	 break; 
      			      }*/
      			      if("".equals(e.currentLocation)){
      			    	  throw new RuntimeException("Current location is null");
      			      }
      			      
      				allEmployeeList.add(e);
      			      
      					    count++;
            		}
            	}
            	//Collections.sort(employeeList);	     	
            }
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		
		
		
		//Populate the location Array to be used in recursive function
		
		
		// File Writing tasks

		 
		System.out.println("Total number of employees loaded : "+ allEmployeeList.size());
		 
	}
		
	public void convertToLightWeightDataStructures() {
		locationArray = new  Integer[locations.keySet().size()];
		int i =0;
		for(String loc : locations.keySet()){
			//System.out.println("LocationList: "+ loc + "  "+locations.get(loc));
			locationArray[i] = locations.get(loc);
		    ++i;
		}
		
		
		//Populate the employee  Array to be used in recursive function
		//Correct the abnormalities in the request fields
		if(employeeList.size() > 0){
			employees = new BasicEmployee[employeeList.size()];
			int j =0 ;
			for (Employee e : employeeList) {
					//for()
				employees[j] = new BasicEmployee(j,e.getEmployeeNo(),
						getLocationId(e.getRequest1()),
							getLocationId(e.getRequest2()),
								getLocationId(e.getRequest3()),
										getLocationId(e.getCurrentLocation() ));
				if(e.currentLocationServicePeriod < 5){
					employees[j].setMarked(true);
				}
				
				normalizeUnrequestedLocatons(employees[j]);
				++j;
			}
		}
		
				
	}
	
	public void filterEmployees() {
		for (Employee e : allEmployeeList) {
			String request1 = e.getRequest1();
			String request2 = e.getRequest2();
			String request3 = e.getRequest3();
			String currentLocation = e.getCurrentLocation();
			int currentLocationServicePeriod = e.getCurrentLocationServicePeriod();

			   if(currentLocationServicePeriod < 5 && (("".equals(request1.trim()) && "".equals(request2.trim()) && "".equals(request3.trim()) ) || (currentLocation.trim().equals(request1.trim()))   )){
			    	  noRequestEmployees.add(e);
			      }else if(currentLocationServicePeriod >= 5 && (("".equals(request1.trim()) && "".equals(request2.trim()) && "".equals(request3.trim()) ))) {
			    	  moreThan5AndNoRequestEmployees.add(e);  
			    	  locations.add(e.getCurrentLocation());// Vacates the locations
			      }else if(currentLocationServicePeriod < 5){
			      	  employeeList.add(e);
			      	  locations.addWithoutIncrement(e.getCurrentLocation());
			      	  reservedLocations.add(e.getCurrentLocation());
			      }else{
			    	  employeeList.add(e);
			      	  locations.add(e.getCurrentLocation());
			      }

			   }
		Collections.sort(employeeList);	
		
	}
	
	
	public void naiveMethod(){ 	  
	 	   for (int i = 0; i < employees.length; i++) { 		  
	 		   if(employees[i].getRequest1() != LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getRequest1()] > 0){
	 			   employees[i].setAssignedLocation(REQUEST_1);
	 			   --locationArray[employees[i].getRequest1()];
	 			  if(employees[i].isMarked()){
	 				  ++locationArray[employees[i].getCurrentLocation()];
	 				 reservedLocations.reduce(getRealLocationId(employees[i].getCurrentLocation()));
	 			  }
	 			   
	 		   }else if(employees[i].getRequest2() != -1 && locationArray[employees[i].getRequest2()] > 0){
	 			   employees[i].setAssignedLocation(REQUEST_2); 
	 			   --locationArray[employees[i].getRequest2()];
	 			  if(employees[i].isMarked()){
	 				  ++locationArray[employees[i].getCurrentLocation()];
	 				 reservedLocations.reduce(getRealLocationId(employees[i].getCurrentLocation()));
	 			  }
	 			   
	 		   }else if(employees[i].getRequest3() != -1 && locationArray[employees[i].getRequest3()] > 0){
	 			   employees[i].setAssignedLocation(REQUEST_3); 
	 			   --locationArray[employees[i].getRequest3()];
	 			  if(employees[i].isMarked()){
	 				  ++locationArray[employees[i].getCurrentLocation()];
	 				 reservedLocations.reduce(getRealLocationId(employees[i].getCurrentLocation()));
	 			  }
	 			   
	 		   }else if(employees[i].isMarked()){
	 			  employees[i].setAssignedLocation(CURRENT_LOCATION); 
	 			  reservedLocations.reduce(getRealLocationId(employees[i].getCurrentLocation()));
				
	 		   }else if(employees[i].getCurrentLocation() != -1 && locationArray[employees[i].getCurrentLocation()] > 0){
	 			   employees[i].setAssignedLocation(CURRENT_LOCATION); 
	 			   --locationArray[employees[i].getCurrentLocation()];
	 		   }else{
	 			   employees[i].setAssignedLocation(NO_LOCATION);
	 		   }
	 			  
	 	   } 	 
	 	 evaluateAndOutputResults(employees);  
	   }
	
	
	
	
	
	
	
	
	
	//	Integer[] employeeAssignments;	
	public  Integer[]  findSolution( Integer[] employeeAssignments,  Integer[] beginLocations, int k  ){
		
		if(k == employees.length ){
			return employeeAssignments;
		}/*else if(employeeAssignments[k] == 4){
			return employeeAssignments;
		}*/
		/*
		 * 1- request 1
		 * 2- request 2
		 * 3- request 3
		 * 0- current location
		 * 4- give location where maximum oppotunties available
		 * */
		int choices[] = {1,2,3,0,4};
		Integer[] solution = null;
		
		for (int i : choices) {			
			Integer[] pathSolution = null;
			/*Integer[] assignment = new Integer[employeeAssignments.length];;
			Integer[]  endLocations = new Integer[beginLocations.length];*/	
			Integer[] assignment = null;
			Integer[]  endLocations = null;
		
			switch(i){
					case 1:
							if (employees[k].getRequest1() != -1 && beginLocations[employees[k].getRequest1()] > 0){
								 assignment = new Integer[employeeAssignments.length];
								 endLocations = new Integer[beginLocations.length];
								 System.arraycopy(employeeAssignments, 0, assignment, 0, employeeAssignments.length);
								 System.arraycopy(beginLocations, 0, endLocations, 0, beginLocations.length);								
								 endLocations[employees[k].getRequest1()]= endLocations[employees[k].getRequest1()] -1;	
													 
							}
						break;
					case 2:
							if (employees[k].getRequest2() != -1 &&  beginLocations[employees[k].getRequest2()] > 0){
								 assignment = new Integer[employeeAssignments.length];
								 endLocations = new Integer[beginLocations.length];
								 System.arraycopy(employeeAssignments, 0, assignment, 0, employeeAssignments.length);
								 System.arraycopy(beginLocations, 0, endLocations, 0, beginLocations.length);
								
								 endLocations[employees[k].getRequest2()] = endLocations[employees[k].getRequest2()] -1;
												 
							}
						break;
					case 3:
							if (employees[k].getRequest3() != -1 && beginLocations[employees[k].getRequest3()] > 0){
								 assignment = new Integer[employeeAssignments.length];
								 endLocations = new Integer[beginLocations.length];
								 System.arraycopy(employeeAssignments, 0, assignment, 0, employeeAssignments.length);
								 System.arraycopy(beginLocations, 0, endLocations, 0, beginLocations.length);								 
								 endLocations[employees[k].getRequest3()] = endLocations[employees[k].getRequest3()] -1;
							
							}
						break;
					case 0:
						if (employees[k].getCurrentLocation() != -1 && beginLocations[employees[k].getCurrentLocation()] > 0){
								assignment = new Integer[employeeAssignments.length];
								endLocations = new Integer[beginLocations.length];
								 System.arraycopy(employeeAssignments, 0, assignment, 0, employeeAssignments.length);
								 System.arraycopy(beginLocations, 0, endLocations, 0, beginLocations.length);								
								 endLocations[employees[k].getCurrentLocation()]= endLocations[employees[k].getCurrentLocation()]-1;
							
						}
						break;
					case 4:
								assignment = new Integer[employeeAssignments.length];
								endLocations = new Integer[beginLocations.length];
								 System.arraycopy(employeeAssignments, 0, assignment, 0, employeeAssignments.length);
								 System.arraycopy(beginLocations, 0, endLocations, 0, beginLocations.length);
																		
						break;	
			}		
			
		  
		   	 if(assignment != null){
		   		 assignment[k] = i;
				 pathSolution = findSolution(assignment,endLocations,k+1 );
				 solution = getBetterSolution(solution, pathSolution);
				 //break;
		   	 }
		   	 
		 	
			
		}

	return solution;
}
		
    public  Integer[]  findSolutionBackOff( Integer[] employeeAssignments,  Integer[] beginLocations, int k  ){
		System.out.println("Ssssssss");
		if(k == employees.length ){
			return employeeAssignments;
		}/*else if(employeeAssignments[k] == 4){
			return employeeAssignments;
		}*/
		/*
		 * 1- request 1
		 * 2- request 2
		 * 3- request 3
		 * 0- current location
		 * 4- give location where maximum oppotunties available
		 * */
		int choices[] = {1,2,3,0,4};
		Integer[] solution = null;
		Integer[] pathSolution = null;
		
		/*if((employees[k].getRequest1() == -1)  && (employees[k].getRequest2() == -1 ) && (employees[k].getRequest3() == -1) ){
			Integer[] assignment = null;
			Integer[]  endLocations = null;
			assignment = new Integer[employeeAssignments.length];
			 endLocations = new Integer[beginLocations.length];
			 System.arraycopy(employeeAssignments, 0, assignment, 0, employeeAssignments.length);
			 System.arraycopy(beginLocations, 0, endLocations, 0, beginLocations.length);
			 assignment[k] = 4;
			 pathSolution = findSolutionBackOff(assignment,endLocations,k+1 );
		}else{*/
		
		for (int i : choices) { 			
			
			/*Integer[] assignment = new Integer[employeeAssignments.length];;
			Integer[]  endLocations = new Integer[beginLocations.length];*/	
			Integer[] assignment = null;
			Integer[]  endLocations = null;
			
			
				switch(i){
					case 1:
							if (employees[k].getRequest1() != -1 && beginLocations[employees[k].getRequest1()] > 0){
								 assignment = new Integer[employeeAssignments.length];
								 endLocations = new Integer[beginLocations.length];
								 System.arraycopy(employeeAssignments, 0, assignment, 0, employeeAssignments.length);
								 System.arraycopy(beginLocations, 0, endLocations, 0, beginLocations.length);								
								 endLocations[employees[k].getRequest1()]= endLocations[employees[k].getRequest1()] -1;	
													 
							}
						break;
					case 2:
							if (employees[k].getRequest2() != -1 &&  beginLocations[employees[k].getRequest2()] > 0){
								 assignment = new Integer[employeeAssignments.length];
								 endLocations = new Integer[beginLocations.length];
								 System.arraycopy(employeeAssignments, 0, assignment, 0, employeeAssignments.length);
								 System.arraycopy(beginLocations, 0, endLocations, 0, beginLocations.length);
								
								 endLocations[employees[k].getRequest2()] = endLocations[employees[k].getRequest2()] -1;
												 
							}
						break;
					case 3:
							if (employees[k].getRequest3() != -1 && beginLocations[employees[k].getRequest3()] > 0){
								 assignment = new Integer[employeeAssignments.length];
								 endLocations = new Integer[beginLocations.length];
								 System.arraycopy(employeeAssignments, 0, assignment, 0, employeeAssignments.length);
								 System.arraycopy(beginLocations, 0, endLocations, 0, beginLocations.length);								 
								 endLocations[employees[k].getRequest3()] = endLocations[employees[k].getRequest3()] -1;
							
							}
						break;
					case 0:
						if (employees[k].getCurrentLocation() != -1 && beginLocations[employees[k].getCurrentLocation()] > 0){
								assignment = new Integer[employeeAssignments.length];
								endLocations = new Integer[beginLocations.length];
								 System.arraycopy(employeeAssignments, 0, assignment, 0, employeeAssignments.length);
								 System.arraycopy(beginLocations, 0, endLocations, 0, beginLocations.length);								
								 endLocations[employees[k].getCurrentLocation()]= endLocations[employees[k].getCurrentLocation()]-1;
							
						}
						break;
					case 4:
								assignment = new Integer[employeeAssignments.length];
								endLocations = new Integer[beginLocations.length];
								 System.arraycopy(employeeAssignments, 0, assignment, 0, employeeAssignments.length);
								 System.arraycopy(beginLocations, 0, endLocations, 0, beginLocations.length);
								return solution;										
						//break;	
			}		
			
		  
		   	 if(assignment != null){
		   		 assignment[k] = i;
				 pathSolution = findSolutionBackOff(assignment,endLocations,k+1 );
				 break;
		   	 }
		   	 
		 	// solution = getBetterSolution(solution, pathSolution);
			
		}
	//}
		 solution = getBetterSolution(solution, pathSolution);

	return solution;
}
	
       
    /*
     *	Non-Recursive – (When req2 cannot be given to sources, an above employee can vacate  source req1, req2)
     */
    public void checkBackEveryReqWithAboveEmployees(){
  
     	
  	   for (int i = 0; i < employees.length; i++) {   		  
  		   
  		    if(employees[i].getRequest1() != -1 && locationArray[employees[i].getRequest1()] > 0){
  			   employees[i].setAssignedLocation(1);
  			   --locationArray[employees[i].getRequest1()];
  			   continue;
  		   }
  		   
  		   if(employees[i].getRequest2() != -1 && locationArray[employees[i].getRequest2()] < 1){
   			  if( backOffAtGivenRequestForAll(i,2)){ // As request 2 does not have vacancies check whether someone above can sacrifice request 1 and move on with request 2 
  				  /* employees[i].setAssignedLocation(2); 
  					 --	locationArray[employees[i].getRequest2()];*/
  					continue;
  				}  		
   		   }else if(employees[i].getRequest2() != -1 && locationArray[employees[i].getRequest2()] > 0) {
   			   employees[i].setAssignedLocation(2); 
 				 --	locationArray[employees[i].getRequest2()];
 				 continue;
   		   }
  		   
  		   
  		  if(employees[i].getRequest3() != -1 && locationArray[employees[i].getRequest3()] < 1){
   			  if( backOffAtGivenRequestForAll(i,3)){ // As request 3 does not have vacancies check whether someone above can sacrifice request 2 and move on with request 3
  				/*   employees[i].setAssignedLocation(3); 
  					 --	locationArray[employees[i].getRequest3()];*/
  					continue;
  				}  		
   		   }else if(employees[i].getRequest3() != -1 && locationArray[employees[i].getRequest3()] > 0) {
   			   employees[i].setAssignedLocation(3); 
 				 --	locationArray[employees[i].getRequest3()];
 				 continue;
   		   }
  		   
  		 if(employees[i].getCurrentLocation() != -1 && locationArray[employees[i].getCurrentLocation()] < 1){
  			  if( backOffAtGivenRequestForAll(i,0)){ // As current location  does not have vacancies check whether someone above can sacrifice request 3 and move on with current
 				 /*  employees[i].setAssignedLocation(0); 
 					 --	locationArray[employees[i].getCurrentLocation()];*/
 					 continue;
 				}  		
  		   }else if(employees[i].getCurrentLocation() != -1 && locationArray[employees[i].getCurrentLocation()] > 0) {
  			   employees[i].setAssignedLocation(0); 
 				 --	locationArray[employees[i].getCurrentLocation()];
 				 continue;
  		   }  			 
  		 
  		   
  		  employees[i].setAssignedLocation(4);
  		  
  			  
  	   }
  	   
  	   
  	   evaluateAndOutputResults(employees);
  	   
     }
        
    public void checkBackEveryReqWithAboveEmployeesWithOneDownPenalty(){
    	  
     	
   	   for (int i = 0; i < employees.length; i++) {   
   		  
   		   
   		    if(employees[i].getRequest1() != -1 && locationArray[employees[i].getRequest1()] > 0){
   			   employees[i].setAssignedLocation(1);
   			   --locationArray[employees[i].getRequest1()];
   			   continue;
   		   }
   		   
   		   if(employees[i].getRequest2() != -1 && locationArray[employees[i].getRequest2()] < 1){
    			  if( backOffAtGivenRequestForAllWithOneDownPenalty(i,2)){ // As request 2 does not have vacancies check whether someone above can sacrifice request 1 and move on with request 2 
   				  /* employees[i].setAssignedLocation(2); 
   					 --	locationArray[employees[i].getRequest2()];*/
   					continue;
   				}  		
    		   }else if(employees[i].getRequest2() != -1 && locationArray[employees[i].getRequest2()] > 0) {
    			   employees[i].setAssignedLocation(2); 
  				 --	locationArray[employees[i].getRequest2()];
  				 continue;
    		   }
   		   
   		   
   		  if(employees[i].getRequest3() != -1 && locationArray[employees[i].getRequest3()] < 1){
    			  if( backOffAtGivenRequestForAllWithOneDownPenalty(i,3)){ // As request 3 does not have vacancies check whether someone above can sacrifice request 2 and move on with request 3
   				/*   employees[i].setAssignedLocation(3); 
   					 --	locationArray[employees[i].getRequest3()];*/
   					continue;
   				}  		
    		   }else if(employees[i].getRequest3() != -1 && locationArray[employees[i].getRequest3()] > 0) {
    			   employees[i].setAssignedLocation(3); 
  				 --	locationArray[employees[i].getRequest3()];
  				 continue;
    		   }
   		   
   		 if(employees[i].getCurrentLocation() != -1 && locationArray[employees[i].getCurrentLocation()] < 1){
   			  if( backOffAtGivenRequestForAllWithOneDownPenalty(i,0)){ // As current location  does not have vacancies check whether someone above can sacrifice request 3 and move on with current
  				 /*  employees[i].setAssignedLocation(0); 
  					 --	locationArray[employees[i].getCurrentLocation()];*/
  					 continue;
  				}  		
   		   }else if(employees[i].getCurrentLocation() != -1 && locationArray[employees[i].getCurrentLocation()] > 0) {
   			   employees[i].setAssignedLocation(0); 
  				 --	locationArray[employees[i].getCurrentLocation()];
  				 continue;
   		   }  			 
   		 
   		   
   		  employees[i].setAssignedLocation(4);
   		  
   			  
   	   }
   	   
   	   
   	   evaluateAndOutputResults(employees);
   	   
      }
          
    
       
    private boolean backOffAtNoLocation(int employeeId , int locationId  ){
    	for(int i =employeeId-1 ; i > 0 ; --i){
    		if(employees[i].getAssignedLocation() == 3 && (employees[i].getRequest3() == locationId) && 
    				( employees[i].getCurrentLocation() !=  LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getCurrentLocation()] > 0)  ){
    			//if(employees[i].getRequest1() == locationId){
				//if( employees[i].getCurrentLocation() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getCurrentLocation()] > 0){
					locationArray[employees[i].getCurrentLocation()]--;
					locationArray[employees[i].getRequest3()]++;
					employees[i].setAssignedLocation(0);
					return true;
				//}
    		
    			//}
    		}else if(employees[i].getAssignedLocation() == 2 && (employees[i].getRequest2() == locationId) &&
    					( employees[i].getRequest3() !=  LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getRequest3()] > 0)){
    			//if(employees[i].getRequest1() == locationId){
				//if( employees[i].getRequest3() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getRequest3()] > 0){
					locationArray[employees[i].getRequest3()]--;
					locationArray[employees[i].getRequest2()]++;
					employees[i].setAssignedLocation(3);
					return true;
				//}
			//}
    		}else if(employees[i].getAssignedLocation() == 1 && (employees[i].getRequest1() == locationId) && 
    					( employees[i].getRequest2() !=  LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getRequest2()] > 0)){
    			//if(employees[i].getRequest1() == locationId){
				//if( employees[i].getRequest2() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getRequest2()] > 0){
					locationArray[employees[i].getRequest2()]--;
					locationArray[employees[i].getRequest1()]++;
					employees[i].setAssignedLocation(2);
					return true;
				//}
			//}
    		}
    		
    	}
    	return false;	
    }
        
    private boolean backOffAtGivenRequest(int employeeId , int locationId , int request ){
    	int checkReq = 0;
    	
    	
    	if(request == 2){			// my request is 2 check whether I can remove req 1 from above assigned
    		checkReq =1; 
    	}else if(request == 3){		// my request is 3 check whether I can remove req 2 from above assigned
    		checkReq = 2;
    	}else if(request == 0){		// my request match  is 0 (current loc)  check whether I can remove req 3 from above
    		checkReq = 3;
    	}if(request == 1){			// my request is 1 check whether I can remove req 1 from above assigned
    		checkReq =1; 
    	}
    	/*else {
			checkReq = 0;
		}*/
    	
    	for(int i =employeeId-1 ; i > 0 ; --i){
    		if(checkReq == 3  && employees[i].getAssignedLocation() == 3 && (employees[i].getRequest3() == locationId && employees[i].getCurrentLocation() !=  LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getCurrentLocation()] > 0)){
    			//if(employees[i].getRequest1() == locationId){
				//if( employees[i].getCurrentLocation() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getCurrentLocation()] > 0){
					locationArray[employees[i].getCurrentLocation()]--;
					locationArray[employees[i].getRequest3()]++;
					employees[i].setAssignedLocation(0);
					return true;
			//	}
    		
    			//}
    		}else if(checkReq == 2  && employees[i].getAssignedLocation() == 2 && (employees[i].getRequest2() == locationId) && ( employees[i].getRequest3() !=  LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getRequest3()] > 0)){ // my request is 3 check whether I can remove req 2 assigned from above and get me a location
    			//if(employees[i].getRequest1() == locationId){
				//if( employees[i].getRequest3() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getRequest3()] > 0){
					locationArray[employees[i].getRequest3()]--;
					locationArray[employees[i].getRequest2()]++;
					employees[i].setAssignedLocation(3);
					return true;
				//}
			//}
    		}else if(checkReq == 1  && employees[i].getAssignedLocation() == 1 && (employees[i].getRequest1() == locationId) && ( employees[i].getRequest2() !=  LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getRequest2()] > 0)){
    			//if(employees[i].getRequest1() == locationId){
			//	if( employees[i].getRequest2() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getRequest2()] > 0){ // check whether his request 2 can be satisfied
					locationArray[employees[i].getRequest2()]--;
					locationArray[employees[i].getRequest1()]++;
					employees[i].setAssignedLocation(2);
					return true;
			//	}
			//}
    		}/*else if(checkReq == 0  &&employees[i].getAssignedLocation() == 0 && (employees[i].getRequest1() == locationId) && ( employees[i].getRequest2() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getRequest2()] > 0)){
    			//if(employees[i].getRequest1() == locationId){
			//	if( employees[i].getRequest2() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getRequest2()] > 0){
					locationArray[employees[i].getRequest2()]--;
					locationArray[employees[i].getRequest1()]++;
					employees[i].setAssignedLocation(2);
					return true;
			//	}
			//}
    		}*/
    		
    		
    	}
    	
    	return false;	
    }
    
    private boolean backOffAtGivenRequestForAll(int employeeId  , int request ){
    	int checkReq = 0;
    	int otherRequests[] =null;
    	
    	if(request == 2){			// my request is 2 check whether I can remove req 1 from above assigned
    		//checkReq =1;
    		int [] otherRequests1  = {1,2};
    		otherRequests = otherRequests1;
    	}else if(request == 3){		// my request is 3 check whether I can remove req 2 from above assigned
    		//checkReq = 2;
    		int [] otherRequests1  = {1,2,3};
    		otherRequests = otherRequests1;
    	}else if(request == 0){		// my request match  is 0 (current loc)  check whether I can remove req 3 from above
    		//checkReq = 3;
    		int [] otherRequests1  = {1,2,3,0};
    		otherRequests = otherRequests1;
    	}
    	/*else {
			checkReq = 0;
		}*/
    	
    		
    	for(int j =0; j < otherRequests.length ; ++j){
    		int sourceReqId  = otherRequests[j];
    	    int locationId = LOCATION_NOT_IN_VACANCY_LIST ;
    	    
    	    if(sourceReqId == 1){
    	    	locationId = employees[employeeId].getRequest1();
    	    }else if(sourceReqId == 2){
    	    	locationId = employees[employeeId].getRequest2();
    	    }else if(sourceReqId == 3){
    	    	locationId = employees[employeeId].getRequest3();
    	    }
    	    if(locationId == LOCATION_NOT_IN_VACANCY_LIST){
    	    	continue;
    	    }
    	    
	    	for(int i =employeeId-1 ; i > 0 ; --i){
	    		if(/*checkReq == 3  &&*/ employees[i].getAssignedLocation() == 3 && (employees[i].getRequest3() == locationId && employees[i].getCurrentLocation() !=  LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getCurrentLocation()] > 0)){
	    			//if(employees[i].getRequest1() == locationId){
					//if( employees[i].getCurrentLocation() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getCurrentLocation()] > 0){
						locationArray[employees[i].getCurrentLocation()]--;
						locationArray[employees[i].getRequest3()]++;
						employees[i].setAssignedLocation(0);
						//For source employee
						employees[employeeId].setAssignedLocation(sourceReqId);
			  			--locationArray[locationId];  // no need to do if locationArray[employees[i].getRequest3()]++; was not increase. For clarity incresease then decreased
						return true;
				//	}
	    		
	    			//}
	    		}else if(/*checkReq == 2  &&*/ employees[i].getAssignedLocation() == 2 && (employees[i].getRequest2() == locationId) && ( employees[i].getRequest3() !=  LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getRequest3()] > 0)){ // my request is 3 check whether I can remove req 2 assigned from above and get me a location
	    			//if(employees[i].getRequest1() == locationId){
					//if( employees[i].getRequest3() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getRequest3()] > 0){
						locationArray[employees[i].getRequest3()]--;
						locationArray[employees[i].getRequest2()]++;
						employees[i].setAssignedLocation(3);
						//For source employee
						 employees[employeeId].setAssignedLocation(sourceReqId);
						 --locationArray[locationId];
						return true;
					//}
				//}
	    		}else if(/*checkReq == 1&&*/   employees[i].getAssignedLocation() == 1 && (employees[i].getRequest1() == locationId) && ( employees[i].getRequest2() !=  LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getRequest2()] > 0)){
	    			//if(employees[i].getRequest1() == locationId){
				//	if( employees[i].getRequest2() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getRequest2()] > 0){ // check whether his request 2 can be satisfied
						locationArray[employees[i].getRequest2()]--;
						locationArray[employees[i].getRequest1()]++;
						employees[i].setAssignedLocation(2);
						//For source employee
						 employees[employeeId].setAssignedLocation(sourceReqId);
			  			  --locationArray[locationId];
						return true;
				//	}
				//}
	    		}/*else if(checkReq == 0  &&employees[i].getAssignedLocation() == 0 && (employees[i].getRequest1() == locationId) && ( employees[i].getRequest2() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getRequest2()] > 0)){
	    			//if(employees[i].getRequest1() == locationId){
				//	if( employees[i].getRequest2() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getRequest2()] > 0){
						locationArray[employees[i].getRequest2()]--;
						locationArray[employees[i].getRequest1()]++;
						employees[i].setAssignedLocation(2);
						return true;
				//	}
				//}
	    		}*/
	    		
	    		
	    	}
    	}
    	return false;	
    }
    
    private boolean backOffAtGivenRequestForAllWithOneDownPenalty(int employeeId  , int request ){
    	int checkReq = 0;
    	int otherRequests[] =null;
    	
    	if(request == 2){			// my request is 2 check whether I can remove req 1 from above assigned
    		checkReq =1;
    		int [] otherRequests1  = {1,2};
    		otherRequests = otherRequests1;
    	}else if(request == 3){		// my request is 3 check whether I can remove req 2 from above assigned
    		checkReq = 2;
    		int [] otherRequests1  = {1,2,3};
    		otherRequests = otherRequests1;
    	}else if(request == 0){		// my request match  is 0 (current loc)  check whether I can remove req 3 from above
    		checkReq = 3;
    		int [] otherRequests1  = {1,2,3,0};
    		otherRequests = otherRequests1;
    	}
    	/*else {
			checkReq = 0;
		}*/
    	
    		
    	for(int j =0; j < otherRequests.length ; ++j){
    		int sourceReqId  = otherRequests[j];
    	    int locationId = -1 ;
    	    
    	    if(sourceReqId == 1){
    	    	locationId = employees[employeeId].getRequest1();
    	    }else if(sourceReqId == 2){
    	    	locationId = employees[employeeId].getRequest2();
    	    }else if(sourceReqId == 3){
    	    	locationId = employees[employeeId].getRequest3();
    	    }
    	    if(locationId == LOCATION_NOT_IN_VACANCY_LIST){
    	    	continue;
    	    }
    	    
	    	for(int i =employeeId-1 ; i > 0 ; --i){
	    		if(checkReq == 3  && employees[i].getAssignedLocation() == 3 && (employees[i].getRequest3() == locationId && employees[i].getCurrentLocation() !=  LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getCurrentLocation()] > 0)){
	    			//if(employees[i].getRequest1() == locationId){
					//if( employees[i].getCurrentLocation() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getCurrentLocation()] > 0){
						locationArray[employees[i].getCurrentLocation()]--;
						locationArray[employees[i].getRequest3()]++;
						employees[i].setAssignedLocation(0);
						//For source employee
						employees[employeeId].setAssignedLocation(sourceReqId);
			  			--locationArray[locationId];
						return true;
				//	}
	    		
	    			//}
	    		}else if(checkReq == 2  && employees[i].getAssignedLocation() == 2 && (employees[i].getRequest2() == locationId) && ( employees[i].getRequest3() !=  LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getRequest3()] > 0)){ // my request is 3 check whether I can remove req 2 assigned from above and get me a location
	    			//if(employees[i].getRequest1() == locationId){
					//if( employees[i].getRequest3() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getRequest3()] > 0){
						locationArray[employees[i].getRequest3()]--;
						locationArray[employees[i].getRequest2()]++;
						employees[i].setAssignedLocation(3);
						//For source employee
						 employees[employeeId].setAssignedLocation(sourceReqId);
						 --locationArray[locationId];
						return true;
					//}
				//}
	    		}else if(checkReq == 1 &&   employees[i].getAssignedLocation() == 1 && (employees[i].getRequest1() == locationId) && ( employees[i].getRequest2() !=  LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getRequest2()] > 0)){
	    			//if(employees[i].getRequest1() == locationId){
				//	if( employees[i].getRequest2() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getRequest2()] > 0){ // check whether his request 2 can be satisfied
						locationArray[employees[i].getRequest2()]--;
						locationArray[employees[i].getRequest1()]++;
						employees[i].setAssignedLocation(2);
						//For source employee
						 employees[employeeId].setAssignedLocation(sourceReqId);
			  			  --locationArray[locationId];
						return true;
				//	}
				//}
	    		}/*else if(checkReq == 0  &&employees[i].getAssignedLocation() == 0 && (employees[i].getRequest1() == locationId) && ( employees[i].getRequest2() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getRequest2()] > 0)){
	    			//if(employees[i].getRequest1() == locationId){
				//	if( employees[i].getRequest2() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getRequest2()] > 0){
						locationArray[employees[i].getRequest2()]--;
						locationArray[employees[i].getRequest1()]++;
						employees[i].setAssignedLocation(2);
						return true;
				//	}
				//}
	    		}*/
	    		
	    		
	    	}
    	}
    	return false;	
    }
       
    private boolean backOffAtGivenRequestSeeManyOptions(int employeeId , int locationId , int request ){
    	int checkReq = 0;
    	int checkReqLocation =0;
    	
    	if(request == 2){			// my request is 2 check whether I can remove req 1 from above assigned
    		checkReq =1; 
    	}else if(request == 3){		// my request is 3 check whether I can remove req 2 from above assigned
    		checkReq = 2;
    	}else if(request == 0){		// my request match  is 0 (current loc)  check whether I can remove req 3 from above
    		checkReq = 3;
    	}/*else {
			checkReq = 0;
		}*/
    	
    	for(int i =employeeId-1 ; i > 0 ; --i){
    		if(checkReq == 3  && employees[i].getAssignedLocation() == 3 && (employees[i].getRequest3() == locationId && employees[i].getCurrentLocation() !=  LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getCurrentLocation()] > 0)){
    			//if(employees[i].getRequest1() == locationId){
				//if( employees[i].getCurrentLocation() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getCurrentLocation()] > 0){
					locationArray[employees[i].getCurrentLocation()]--;
					locationArray[employees[i].getRequest3()]++;
					employees[i].setAssignedLocation(0);
					return true;
			//	}
    		
    			//}
    		}else if(checkReq == 2  && employees[i].getAssignedLocation() == 2 && (employees[i].getRequest2() == locationId) && ( employees[i].getRequest3() !=  LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getRequest3()] > 0)){ // my request is 3 check whether I can remove req 2 assigned from above and get me a location
    			//if(employees[i].getRequest1() == locationId){
				//if( employees[i].getRequest3() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getRequest3()] > 0){
					locationArray[employees[i].getRequest3()]--;
					locationArray[employees[i].getRequest2()]++;
					employees[i].setAssignedLocation(3);
					return true;
				//}
			//}
    		}else if(checkReq == 1  && employees[i].getAssignedLocation() == 1 && (employees[i].getRequest1() == locationId) && ( employees[i].getRequest2() !=  LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getRequest2()] > 0)){
    			//if(employees[i].getRequest1() == locationId){
			//	if( employees[i].getRequest2() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getRequest2()] > 0){ // check whether his request 2 can be satisfied
					locationArray[employees[i].getRequest2()]--;
					locationArray[employees[i].getRequest1()]++;
					employees[i].setAssignedLocation(2);
					return true;
			//	}
			//}
    		}/*else if(checkReq == 0  &&employees[i].getAssignedLocation() == 0 && (employees[i].getRequest1() == locationId) && ( employees[i].getRequest2() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getRequest2()] > 0)){
    			//if(employees[i].getRequest1() == locationId){
			//	if( employees[i].getRequest2() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getRequest2()] > 0){
					locationArray[employees[i].getRequest2()]--;
					locationArray[employees[i].getRequest1()]++;
					employees[i].setAssignedLocation(2);
					return true;
			//	}
			//}
    		}*/
    		
    		
    	}
    	
    	return false;	
    }
    
	private int calculateTotal(BasicEmployee[] employees){
		int unresolved = Integer.MAX_VALUE;		
		if(employees != null){
			unresolved=0;
		for (int i = 0; i < employees.length; i++) {
			if(employees[i].getAssignedLocation() == 4){
				unresolved++;
			}
		}
		}
	//	System.out.println("unresolved: " + unresolved);
	return unresolved;
	}
	
	private int getMaxLocationId(Integer[] locs){
		int max =0;
		int maxId =0;
		for (int i = 0; i < locs.length; i++) {
			if(max < locs[i]){
				max = locs[i];
				maxId = i;
			}
		}
		return maxId;
	}
	
	private void printEmployess(){
		for (int i = 0; i < employees.length; i++) {		
			//System.out.println("Employee: " +i+" "+employeeList.get(i).getEmployeeNo()+" "+employeeList.get(i).getRequest1()+" "+employees[i].getRequest2());
			System.out.println("Employee: " +i+" "+employeeList.get(i).getEmployeeNo()+" "+employees[i].getRequest1()+" "+employees[i].getRequest2()+" "+employees[i].getRequest3()+" "+employees[i].getAssignedLocation());
		}
	}
	
	private void printLocations(){
		for (int i = 0; i < locationArray.length; i++) {
			System.out.println("Location: "+i+" "+locationArray[i]);
		}
	}
		
	private int getLocationId(String loc){
		
    	int id =0;
		System.out.println(loc);
		if(loc.trim().equals("")){
			return -2;
		}
		for(String key : locations.keySet()){
		//	System.out.println("key "+key);
			if(loc.trim().equals(key.trim())){
				return id;
			}
			++id;
		}
		return -1;
	}
		
	public void checkMamximumTransfers(){

		HashMap<String, Integer> request1Map = new HashMap<String, Integer>();
		HashMap<String, Integer> currentLocationMap = new HashMap<String, Integer>();
		int minCount =0;
		
		for(Employee e : employeeList){
			if ( e.getRequest1() != null &&  request1Map.containsKey(e.getRequest1())){
				int x = request1Map.get(e.getRequest1());
				request1Map.put(e.getRequest1(), ++x);				
			}else if(e.getRequest1() != null ){
				request1Map.put(e.getRequest1(), 1);		
			}			
			
			if (e.getCurrentLocation()  != null && currentLocationMap.containsKey(e.getCurrentLocation())){				
				int x = currentLocationMap.get(e.getCurrentLocation());
				currentLocationMap.put(e.getCurrentLocation(), ++x);				
			}else if(e.getCurrentLocation()  != null){
				currentLocationMap.put(e.getCurrentLocation(), 1);		
			}		
		 }
		
		System.out.println("sizeOf Location List "+ locationArray.length);
		System.out.println("sizeOf req1 List "+ request1Map.keySet().size());
	int i =0;	
	for(String currentLocationKey :currentLocationMap.keySet()){
		for(String requset1Key :request1Map.keySet()){
			 if (currentLocationKey.trim().equals(requset1Key.trim())){
				 int currentVal = currentLocationMap.get(currentLocationKey);
				 int reqVal = request1Map.get(requset1Key);
				 if( currentVal > reqVal){
					// System.out.println("Current val :"+ currentVal +"Req Val: "+ reqVal);
					 minCount += reqVal;
				 }else{
					 minCount += currentVal; 
				 }
				 ++i;
				 System.out.println("CurrentLoc : "+i+" "+currentLocationKey+ " count: "+ currentVal + " req Val : "+reqVal +" minCnt : "+minCount );
			//	 break;
			 }
				
		}
	}
	
	System.out.println("Maximum transfers possible : "+ minCount);	
		
	}
	
	public void allocateLocations(){
		HashMap<Employee, String> request1Satisfied = new HashMap<Employee, String>();
		HashMap<Employee, String> request2Satisfied = new HashMap<Employee, String>();
		HashMap<Employee, String> request3Satisfied = new HashMap<Employee, String>();
		ArrayList<Employee> unresolved = new ArrayList<Employee>();
		ArrayList<Employee> noTransfers = new ArrayList<Employee>();
		
		
		for(Employee e : employeeList){
			locations.add(e.getCurrentLocation());
		}
		int count = 0;
		for (String key :locations.keySet()) {
			//System.out.println("Location "+ key +" has "+ locations.get(key) +" number of vacancies");
			count += locations.get(key);
		}		
		System.out.println("Total lcoations: "+ count);
	    int rank = 0;
		for(Employee e : employeeList){
			
			String req1 = e.getRequest1();
			String req2 = e.getRequest2();	
			String req3 = e.getRequest3();
			String currentLoc = e.currentLocation;
			
			int min =Integer.MAX_VALUE;
			int val=0;
			int type =0;
			if(locations.containsKey(req1)){				
				val = getUnResolvedNumber(e, rank, req1, locations);
				if(val < min){
					 min = val;
					type =1;
				}
			}
			if(locations.containsKey(req2)){
				val = getUnResolvedNumber(e, rank, req2, locations);
				if(val < min){
					 min = val;
					 type =2;
				}
			}
			if(locations.containsKey(req3)){
				val = getUnResolvedNumber(e, rank, req3, locations);
				if(val < min){
					 min = val;
					type =3;
				}
			}
			if(locations.containsKey(currentLoc)){
				val = getUnResolvedNumber(e, rank, currentLoc, locations);
				if(val < min){
					 min = val;
					 type = 4;
				}
			}/*else{
				unresolved.add(e);
			}*/
			
			
			switch (type) {
			case 1:
				request1Satisfied.put(e, req1);
				locations.reduce(req1);
				break;
			case 2:
				request2Satisfied.put(e, req2);
				locations.reduce(req2);
				break;
			case 3:
				request3Satisfied.put(e, req3);
				locations.reduce(req3);
				break;
			case 4:
				noTransfers.add(e);
				locations.reduce(currentLoc);
				break;	

			default:
				unresolved.add(e);
				break;
			}
				
			
			rank++;
		}
		
		System.out.println("Count of req 1 satisfied: "+ request1Satisfied.keySet().size());		
		System.out.println("Count of req 2 satisfied: "+ request2Satisfied.keySet().size());
		System.out.println("Count of req 3 satisfied: "+ request3Satisfied.keySet().size());
		System.out.println("Count of no transfers: "+ noTransfers.size());
		System.out.println("Count of unresolved: "+ unresolved.size());
	}
		
	public Integer getUnResolvedNumber(Employee e, int rank , String location, CountingHashMap countingMap){
		HashMap<Employee, String> request1Satisfied = new HashMap<Employee, String>();
		HashMap<Employee, String> request2Satisfied = new HashMap<Employee, String>();
		HashMap<Employee, String> request3Satisfied = new HashMap<Employee, String>();
		ArrayList<Employee> unresolved = new ArrayList<Employee>();
		ArrayList<Employee> noTransfers = new ArrayList<Employee>();
		
		CountingHashMap locations   = (CountingHashMap) countingMap.clone();
		
		if(!locations.containsKey(location)){
			return null;
		}else{
			locations.reduce(location);
		}
		
		//to do : last person  logic
		for (int i = rank+1; i < employeeList.size() ; i++) {
			Employee test = employeeList.get(i);
			String req1 = test.getRequest1();
			String req2 = test.getRequest2();
			String req3 = test.getRequest3();
			
			if(locations.containsKey(req1)){				
				request1Satisfied.put(test, req1);
				locations.reduce(req1);
			}else if(locations.containsKey(req2)){
				request2Satisfied.put(test, req2);
				locations.reduce(req2);
			}else if(locations.containsKey(req3)){
				request3Satisfied.put(test, req3);
				locations.reduce(req3);
			}else if(locations.containsKey(test.currentLocation)){
				noTransfers.add(test);	
				locations.reduce(test.currentLocation);
			}else{
				unresolved.add(test);
			}
		}
		System.out.println(e.getEmployeeNo()+"   "+unresolved.size());
		return unresolved.size();
	}
		
	private Integer[] getBetterSolution(Integer[] sol1, Integer[] sol2){
		
		if(sol1 == null && sol2 == null){
			return null;
		}else if(sol1 == null){
			return sol2;
		}else if(sol2 == null){
			return sol1;
		}else{
			int count1 =0;
			int count2 =0;
			
		/*	for (Integer assignment : sol1) {
				if( assignment == 1){
					count1++;
				}
			}
			
			for (Integer assignment : sol2) {
				if(assignment == 1){
					count2++;
				}
			}*/
			count1 = getWeightedEstimation(sol1);
			count2 = getWeightedEstimation(sol2);
			
			if(count1 >= count2){
				return sol1;
			}else{
				return sol2;
			}
			
		}	
		
	}
	
	private int getWeightedEstimation(Integer[] assignments){ 
		int count =0;
		
		for (Integer assignment : assignments) {
			switch(assignment){
			case 1: //Req 1
				count += 9;
				break;
			case 2: //Req 2
				count += 5;
				break;
			case 3: //Req 2
				count += 3;
				break;
			case 0: //Current location
				count += 1;
				break;
			 case 4://Current location
				count += 0;
				break;	
			}
		}
		
		return count;
	}
		
	private double getPriorityBiasedWeightedEstimation(BasicEmployee[] employees){ 
		double count =0;
		int index = 0;
		int size = employees.length;
		
		for (BasicEmployee employee : employees) {
			++index;
			double priorityFactor = ((double)(size - index)/(double)size);
			int assignment = employee.getAssignedLocation();
			//if(!employee.isMarked()){ //>5
			if(employeeList.get(index-1).getCurrentLocationServicePeriod() >=  5){ //>5
				switch(assignment){
					case 1: //Req 1
						count+= (9 * priorityFactor );
						break;
					case 2: //Req 2
						count += (5 * priorityFactor);
						break;
					case 3: //Req 2
						count += (3 * priorityFactor);
						break;
					case 0: //Current location
						count += (1 * priorityFactor);
						break;
					 case 4://Current location
						count += (-1 *  ( priorityFactor));
						break;	
				}
			}else{
				switch(assignment){
				case 1: //Req 1
					count+= (8 * priorityFactor );
					break;
				case 2: //Req 2
					count += (3.5 * priorityFactor);
					break;
				case 3: //Req 2
					count += (1.5 * priorityFactor);
					break;
				case 0: //Current location
					count += (1.5 * priorityFactor); //Having this is as good as having 
					break;
				 case 4://Current location
					count += (-9 *  ( priorityFactor));
					break;	
			}
			}
		}
		
		return count;
	}
	
	private int getWeightedEstimation(int request1Count,int request2Count,int request3Count, int currentLocationCount, int noLocationCount){ 
		int count =0;		
		count = request1Count * 9 + request2Count * 5 + request3Count * 3 + currentLocationCount*1 + noLocationCount* 0;
		return count;
	}
	
	private String getRealLocationId(int loc){
		int i = 0;
		for ( String locs: locations.keySet()) {
			   if(i ==loc){
				   return locs;
			   }
			++i;
		}
		return "";
	}
	
	public   class CountingHashMap extends HashMap<String, Integer> {		
		
	    public Integer add(String key) {
	    	if(this.containsKey(key)){
		        int currentCount = get(key);
		        currentCount++;
		        this.put(key, currentCount);
	        return currentCount;  
	    	}else{
	    		this.put(key, 1);
	    		return 1;  
	    	}	     
	    }
	    
	    public Integer addWithoutIncrement(String key) {
	    	if(this.containsKey(key)){
		        int currentCount = get(key);
		        return currentCount;  
	    	}else{
	    		this.put(key, 0);
	    		return 0;  
	    	}	     
	    }
	    
	    public Integer reduce(String key) {
	        int currentCount = get(key);
		        if(currentCount == 1){
		        	super.remove(key);
		        }else if(currentCount > 1){
		        	currentCount--;
		        	super.put(key, currentCount);
		        }else{
		        	throw new RuntimeException("Trying to reduce when count is already 0");
		        }
	        return currentCount;    
	    }
	    
	    public Integer reduceWithoutRemoval(String key) {
	        int currentCount = get(key);
		        if(currentCount == 0){
		        		// currentCount--;
		        	super.put(key, 0);
		        }else if(currentCount > 0){
		        	currentCount--;
		        	super.put(key, currentCount);
		        }
	        return currentCount;    
	    }
  }
	
	private void  writeToFile(String data,String path){
		   FileWriter fstream1;
	        BufferedWriter br = null;
	        try {
	            br = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(path),"UTF-8"));
	            br.write(data);
	            br.close();	       
	            System.out.println("Suceesfully writte data to file");
	        } catch (IOException e) {
	                e.printStackTrace();
	        }
		
	}
	
	private void getStats(){
		int noRequestCount = 0;
		int twoRequestCount = 0;
		int oneRequestCount = 0;
		int allRequestCount = 0;
		int moreThan5NotRequested= 0;
		int moreThan5Requested= 0;
		int currentEqualsRequest= 0;
		int lessThan5RequestedSame= 0;
		
		for (Employee e : employeeList) {
			String request1 = e.getRequest1().trim();
			String request2 = e.getRequest2().trim();
			String request3 = e.getRequest3().trim();
			
			
			if("".equals(request1) && "".equals(request2) && "".equals(request3)){
				noRequestCount++;
			}else if(("".equals(request1) && "".equals(request2) && !"".equals(request3)) || ("".equals(request1) && !"".equals(request2) && "".equals(request3)) || (!"".equals(request1) && "".equals(request2) && "".equals(request3))){
				twoRequestCount++;
			}else if(("".equals(request1) && !"".equals(request2) && !"".equals(request3)) || (!"".equals(request1) && !"".equals(request2) && "".equals(request3)) || (!"".equals(request1) && "".equals(request2) && !"".equals(request3))){
				oneRequestCount++;
			}else {
				allRequestCount++;
			}
			
			
			if(e.getCurrentLocation().trim().equals(request1)){
				currentEqualsRequest++;
			}
			
		}
		
		for (Employee e : noRequestEmployees) {
			if(e.currentLocationServicePeriod >5){
				moreThan5NotRequested++;
			}
		}
		
		for (Employee e : employeeList) {
			if(e.currentLocationServicePeriod >5){
				moreThan5Requested++;
			}else{
				if(e.getCurrentLocation().trim().equals(e.getRequest1().trim())){
					lessThan5RequestedSame++;
				}
			}
		}

		   System.out.println("1 Request only : "+ oneRequestCount);
		   System.out.println("2 Request only : "+ twoRequestCount);
		   System.out.println("All Requests : "+ allRequestCount);
		   System.out.println("No Request  : "+noRequestEmployees.size());
		   System.out.println("No Request more than 5  : "+moreThan5NotRequested);
		   System.out.println("Requested more than 5  : "+moreThan5Requested);
		   
		   System.out.println("No Request less than 5  : "+(noRequestEmployees.size() -moreThan5NotRequested));
		   System.out.println("Requested the other less than 5  : "+(employeeList.size()-moreThan5Requested-lessThan5RequestedSame));
		   System.out.println("Requested the same less than 5  : "+lessThan5RequestedSame);
		   System.out.println("current == req : "+ currentEqualsRequest);
		  
	}
	
	int unsatisfyingCount = 0; 
	private BasicEmployee normalizeUnrequestedLocatons(BasicEmployee employee){
		
		if(employee.getRequest1() !=  NO_LOCATION_REQUESTED  && employee.getRequest2() ==  NO_LOCATION_REQUESTED  && employee.getRequest3() ==  NO_LOCATION_REQUESTED ){ //R1 _ _
				employee.setRequest2(employee.getRequest1());
				employee.setRequest3(employee.getRequest1());
		}else if(employee.getRequest1() !=  NO_LOCATION_REQUESTED  && employee.getRequest2() !=  NO_LOCATION_REQUESTED  && employee.getRequest3() ==  NO_LOCATION_REQUESTED ){ //R1 R2 _
				employee.setRequest3(employee.getRequest2());
		}else if(employee.getRequest1() !=  NO_LOCATION_REQUESTED  && employee.getRequest2() ==  NO_LOCATION_REQUESTED  && employee.getRequest3() !=  NO_LOCATION_REQUESTED ){ //R1 _ R3
				employee.setRequest2(employee.getRequest1());					
		}else if(employee.getRequest1() ==  NO_LOCATION_REQUESTED  && employee.getRequest2() !=  NO_LOCATION_REQUESTED  && employee.getRequest3() ==  NO_LOCATION_REQUESTED ){ // _ R2 _
				employee.setRequest1(employee.getRequest2());
				employee.setRequest3(employee.getRequest2());
		}else if(employee.getRequest1() ==  NO_LOCATION_REQUESTED  && employee.getRequest2() !=  NO_LOCATION_REQUESTED  && employee.getRequest3() !=  NO_LOCATION_REQUESTED ){ // _ R2 R3
				employee.setRequest1(employee.getRequest2());				
		}else if(employee.getRequest1() ==  NO_LOCATION_REQUESTED  && employee.getRequest2() ==  NO_LOCATION_REQUESTED  && employee.getRequest3() !=  NO_LOCATION_REQUESTED ){ // _ _ R3
				employee.setRequest1(employee.getRequest3());
				employee.setRequest2(employee.getRequest3());
		}
		
		//Give the current location if all requests unsatisfied
		
		/*if(allRequestsUnsatisfactory(employee.getRequest1(),employee.getRequest2(), employee.getRequest3())){
			System.out.println("Unsatisfying employee :"+ employee.getEmployeeId() );	
			int current = employee.getCurrentLocation();
				employee.setRequest1(current);
				employee.setRequest2(current);
				employee.setRequest3(current);
				
		}*/
		
		if(employee.getRequest1() == NO_LOCATION_REQUESTED){
			employee.setRequest1(employee.getCurrentLocation());
		}else if (employee.getRequest2() == NO_LOCATION_REQUESTED){
			employee.setRequest2(employee.getCurrentLocation());
		}else if (employee.getRequest3() == NO_LOCATION_REQUESTED){
			employee.setRequest3(employee.getCurrentLocation());
		}
		
	//	System.out.println("Unsatisfying count :"+ unsatisfyingCount);
		return employee;
	}
	
	private boolean allRequestsUnsatisfactory(int req1, int req2, int req3){
		if(!(req1 == NO_LOCATION_REQUESTED || req1 == LOCATION_NOT_IN_VACANCY_LIST)){
			return false;
		}
		if(!(req2 == NO_LOCATION_REQUESTED || req2 == LOCATION_NOT_IN_VACANCY_LIST)){
			return false;
		}
		if(!(req3 == NO_LOCATION_REQUESTED || req3 == LOCATION_NOT_IN_VACANCY_LIST)){
			return false;
		}
	return true;	
	}

	private void evaluateAndOutputResults(BasicEmployee[] employees){
		 int request1Count =0;
	 	   int request2Count =0;
	 	   int request3Count =0;
	 	   int currenLocationCount =0;
	 	   int noLocationCount =0;
	 	   int markedRequest1Count =0;
	 	   int markedRequest2Count =0;
	 	   int markedRequest3Count =0;
	 	   int markedCurrenLocationCount =0;
	 	   int markedNoLocationCount =0;
	 	   
	 	  Integer[] assignmets = new Integer[employees.length];
	 	   
		 for (int i = 0; i < employees.length; i++) {
			 assignmets[i] = employees[i].getAssignedLocation();
			   // boolean condition = employees[i].isMarked();
			    boolean condition = employeeList.get(i).getCurrentLocationServicePeriod() < 5;
			    switch(employees[i].getAssignedLocation() ){	 		   
	 		   	case 1:	 		   		
	 		   		if(condition){
	 		   			markedRequest1Count++;
	 		   		}else{
	 		   			request1Count++;
	 		   		}
	 			   break;
	 		   	case 2:
		 		   	if(condition){
	 		   			markedRequest2Count++;
	 		   		}else{
	 		   			request2Count++;
	 		   		}
	 		   		
	 			   break;
	 		   	case 3:
		 		   	if(condition){
	 		   			markedRequest3Count++;
	 		   		}else{
	 		   			request3Count++;
	 		   		} 		   		
	 				break;
	 		   	case 0:
		 		   	if(condition){
	 		   			markedCurrenLocationCount++;
	 		   		}else{
	 		   			currenLocationCount++;
	 		   		} 	
	 		   		
	 		   	 
	 				break;	   
	 		   	case 4:
	 		    	if(condition){
	 		   			markedNoLocationCount++;
	 		   		}else{
	 		   			noLocationCount++;
	 		   		} 	
	 		   		
	 		   	
	 		   	 System.out.println("Employee id : "+employees[i].getEmployeeId()+" "+ employees[i].getRequest1()+" "+employees[i].getRequest2() + " "+ employees[i].getRequest3());
	 		   		break;
	 				
	 		   }
	 		  
	 	   }
	 	   
		 int remainingLocations =0;
		 for (int i = 0; i < locationArray.length; i++) {
			remainingLocations += locationArray[i];
		}
	 	   
	 	   
		 int weight =getWeightedEstimation(assignmets);
	 	 double priorityWeight = getPriorityBiasedWeightedEstimation(employees);  
	 	  System.out.println("Total EMployees: "+ employees.length);
	 	   System.out.println(">=5 Request 1 count: "+ request1Count);
	 	   System.out.println(">=5 Request 2 count: "+ request2Count);
	 	   System.out.println(">=5 Request 3 count: "+ request3Count);
	 	   System.out.println(">=5 Current Location count: "+ currenLocationCount);
	 	   System.out.println(">=5 No Location count: "+ noLocationCount);
	
	 	  
	 	   System.out.println("<5 Request 1 count: "+ markedRequest1Count);
	 	   System.out.println("<5 Request 2 count: "+ markedRequest2Count);
	 	   System.out.println("<5 Request 3 count: "+ markedRequest3Count);
	 	   System.out.println("<5 Current Location count: "+ markedCurrenLocationCount);
	 	   System.out.println("<5 No Location count: "+ markedNoLocationCount);
	 	   
	 	   System.out.println("Total Request 1 count: "+ (markedRequest1Count+request1Count));
	 	   System.out.println("Total Request 2 count: "+ (markedRequest2Count+request2Count));
	 	   System.out.println("Total Request 3 count: "+ (markedRequest3Count+request3Count));
	 	   System.out.println("Total Current Location count: "+ (markedCurrenLocationCount+currenLocationCount));
	 	   System.out.println("Total No Location count: "+ (markedNoLocationCount + noLocationCount));
	 	  
	 	   System.out.println("Normal Weight is : "+ weight);
	 	   System.out.println("Priority Weight is : "+ priorityWeight);
	 	   
	 	   System.out.println("Not considered employees no:  "+  noRequestEmployees.size());
	 	   System.out.println("Remaining Locations : "+ remainingLocations);
	 	   System.out.println("No request and +5 employees : "+ moreThan5AndNoRequestEmployees.size() );
	 	   
	 	 
	}

	private String convertEmployeeDataToString (){
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < employees.length; i++) {
			Employee employee = employeeList.get(i);
			BasicEmployee basicEmployee = employees[i];
			int assignedLocation = basicEmployee.getAssignedLocation();
			
			sb.append(employee.getEmployeeNo()+", ");
			sb.append(employee.getCurrentLocation()+", ");
			sb.append(employee.getRequest1()+", ");
			sb.append(employee.getRequest2()+", ");
			sb.append(employee.getRequest3()+",  ");
			
			switch (assignedLocation) {
			case 1:
				sb.append(employee.getRequest1()+", ");
				break;
			case 2:
				sb.append(employee.getRequest2()+", ");
				break;
			case 3:
				sb.append(employee.getRequest3()+", ");
				break;
			case 0:
				sb.append(employee.getCurrentLocation()+", ");
				break;
			case 4:
				sb.append("rem"+", ");
				break;
    		}
			
			
			sb.append("\n");	
		}
	
		return sb.toString();
		
	}

	public void checkWeightForTransfers(){
	
		int count =0;
		for (int i = 0; i < locationArray.length; i++) {			
			for (int j = 0; j < employees.length; j++) {				
				BasicEmployee employee = employees[j];
				if(employee.getRequest1()!= LOCATION_NOT_IN_VACANCY_LIST && employee.getRequest1() == i && locationArray[i] > 0 && employee.getAssignedLocation() == 9){
					employee.setAssignedLocation(1);
					locationArray[i] = locationArray[i] -1;	
					
					System.out.println("In algo "+ employee.getRequest1() + " "+locationArray[i]);
					if(locationArray[i] == 0){
						++count;
						break;
					}
			}
			}
		}
		
		
		for (int i = 0; i < locationArray.length; i++) {	
			for (int j = 0; j < employees.length; j++) {
				BasicEmployee employee = employees[j];
				if(employee.getRequest2()!= LOCATION_NOT_IN_VACANCY_LIST && employee.getRequest2() == i && locationArray[i] > 0 && employee.getAssignedLocation() == 9){
					employee.setAssignedLocation(2);
					locationArray[i]--;
				}
				
				if(locationArray[i] ==0){
					break;
				}
			}
	//	System.out.println("Location "+i+" "+ locationArray[i] );
		}
		
		

		for (int i = 0; i < locationArray.length; i++) {	
			for (int j = 0; j < employees.length; j++) {
		
			BasicEmployee employee = employees[j];
				if(employee.getRequest3()!= LOCATION_NOT_IN_VACANCY_LIST && employee.getRequest3() == i && locationArray[i] > 0 && employee.getAssignedLocation() == 9){
					employee.setAssignedLocation(3);
					locationArray[i]--;
				}
				
				if(locationArray[i] ==0){
					break;
				}
			}
			
			
	//	System.out.println("Location "+i+" "+ locationArray[i] );
		}
		
		
		for (int i = 0; i < locationArray.length; i++) {	
			for (int j = 0; j < employees.length; j++) {
		
			BasicEmployee employee = employees[j];
				if(employee.getCurrentLocation()!= LOCATION_NOT_IN_VACANCY_LIST && employee.getCurrentLocation() == i && locationArray[i] > 0 && employee.getAssignedLocation() == 9){
					employee.setAssignedLocation(0);
					locationArray[i]--;
				}
				
				if(locationArray[i] ==0){
					break;
				}
			}
		}

		for (int j = 0; j < employees.length; j++) {
			
			BasicEmployee employee = employees[j];
			if(employee.getAssignedLocation() == 9){
				employee.setAssignedLocation(4);
			}
		}
		
		evaluateAndOutputResults(employees);  	
	}
	
	public void algorithmMaximumRequest1(){
		
		int count =0;
		for (int i = 0; i < employees.length; i++) {	
			boolean found = false;
		for (int j = 0; j < locationArray.length; j++) {			
				BasicEmployee employee = employees[i];
				if(employee.getRequest1()== LOCATION_NOT_IN_VACANCY_LIST ){
					break;
				}else if(employee.getRequest1()!= LOCATION_NOT_IN_VACANCY_LIST && employee.getRequest1() == j && locationArray[j] > 0 && employee.getAssignedLocation() == 9){
					employee.setAssignedLocation(REQUEST_1);
					locationArray[j] = locationArray[j] -1;	
					found = true;
					System.out.println("In algo "+ employee.getRequest1() + " "+locationArray[j]);
				break;
				}
			}			
		}

		for (int j = 0; j < employees.length; j++) {
			for (int i = 0; i < locationArray.length; i++) {	
			
				BasicEmployee employee = employees[j];
				if(employee.getRequest2()!= LOCATION_NOT_IN_VACANCY_LIST && employee.getRequest2() == i && locationArray[i] > 0 && employee.getAssignedLocation() == 9){
					employee.setAssignedLocation(2);
					locationArray[i]--;
					break;
				}
			}
		}
		
		
		for (int j = 0; j < employees.length; j++) {
		for (int i = 0; i < locationArray.length; i++) {	
				BasicEmployee employee = employees[j];
				if(employee.getRequest3()!= LOCATION_NOT_IN_VACANCY_LIST && employee.getRequest3() == i && locationArray[i] > 0 && employee.getAssignedLocation() == 9){
					employee.setAssignedLocation(3);
					locationArray[i]--;
					break;
				}
			}
		}
		
		for (int j = 0; j < employees.length; j++) {	
		for (int i = 0; i < locationArray.length; i++) {	
			BasicEmployee employee = employees[j];
				if(employee.getCurrentLocation()!= LOCATION_NOT_IN_VACANCY_LIST && employee.getCurrentLocation() == i && locationArray[i] > 0 && employee.getAssignedLocation() == 9){
					employee.setAssignedLocation(0);
					locationArray[i]--;
					break;
				}
			}
		}

		for (int j = 0; j < employees.length; j++) {			
			BasicEmployee employee = employees[j];
			if(employee.getAssignedLocation() == 9){
				employee.setAssignedLocation(4);
			}
		}
		
		//Smooth out the on priorities
		for (int i = 0; i < employees.length; i++) {	
			BasicEmployee employee = employees[i];
			int assignedLocation = employee.getAssignedLocation();
		    
			if(assignedLocation == 1  ){
		    	continue;
		    }else {
		    	smoothOutMaximumReq1(i, assignedLocation);
		    }	
					
		}
		
		evaluateAndOutputResults(employees);  	
	}
	
	/*After the initial maximum request 1 assignment we try to smooth out assignment. Employees are iterated starting 
	 * from high priority and if he is assigned request 2(for example) we are searching from last employee upwards 
	 * to check whether he can be given request1 by pushing low priority employee next stage */
	public boolean smoothOutMaximumReq1(int employeeId, int request){
		int checkReq = 0;
    	int otherRequests[] =null;
    	int sourceLocation = 0 ;
    	
    	if(request == 2){			
    		int [] otherRequests1  = {1};
    		otherRequests = otherRequests1;
    		sourceLocation = employees[employeeId].getRequest2();
    	}else if(request == 3){		
    		int [] otherRequests1  = {1,2};
    		otherRequests = otherRequests1;
    		sourceLocation = employees[employeeId].getRequest3();
    	}else if(request == 0){		
    		int [] otherRequests1  = {1,2,3};
    		otherRequests = otherRequests1;
    		sourceLocation = employees[employeeId].getCurrentLocation();
    	}else if(request == 4){		
    		int [] otherRequests1  = {1,2,3};
    		otherRequests = otherRequests1;
    		sourceLocation = -1 ;
    	}
    	
    		
    	for(int j =0; j < otherRequests.length ; ++j){
    		int sourceReqId  = otherRequests[j];
    	    int locationId = LOCATION_NOT_IN_VACANCY_LIST ;
    	    
    	    if(sourceReqId == 1){
    	    	locationId = employees[employeeId].getRequest1();
    	    }else if(sourceReqId == 2){
    	    	locationId = employees[employeeId].getRequest2();
    	    }else if(sourceReqId == 3){
    	    	locationId = employees[employeeId].getRequest3();
    	    }else if(sourceReqId == 0){
    	    	locationId = employees[employeeId].getCurrentLocation();
    	    	//continue;
    	    }
    	    if(locationId == LOCATION_NOT_IN_VACANCY_LIST){
    	    	continue;
    	    }
    	    
	    	for(int i = employees.length-1 ; i > employeeId ; --i){
	    		if( employees[i].getAssignedLocation() == 3 && (employees[i].getRequest3() == locationId && employees[i].getCurrentLocation() !=  LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getCurrentLocation()] > 0)){
	    				locationArray[employees[i].getCurrentLocation()]--;
						locationArray[employees[i].getRequest3()]++;
						employees[i].setAssignedLocation(0);
						//For source employee
						employees[employeeId].setAssignedLocation(sourceReqId);
			  			--locationArray[locationId];  // no need to do if locationArray[employees[i].getRequest3()]++; was not increase. For clarity incresease then decreased
						if(sourceLocation != -1){ 	//  Release already assigned one
							++locationArray[sourceLocation]; 
						}
			  			
			  			return true;
				 }else if( employees[i].getAssignedLocation() == 2 && (employees[i].getRequest2() == locationId) && ( employees[i].getRequest3() !=  LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getRequest3()] > 0)){ // my request is 3 check whether I can remove req 2 assigned from above and get me a location
						locationArray[employees[i].getRequest3()]--;
						locationArray[employees[i].getRequest2()]++;
						employees[i].setAssignedLocation(3);
						//For source employee
						 employees[employeeId].setAssignedLocation(sourceReqId);
						 --locationArray[locationId];
						 	if(sourceLocation != -1){  //  Release already assigned one
								++locationArray[sourceLocation]; 
							}
						return true;
					//}
				//}
	    		}else if( employees[i].getAssignedLocation() == 1 && (employees[i].getRequest1() == locationId) && ( employees[i].getRequest2() !=  LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getRequest2()] > 0)){
	    			//if(employees[i].getRequest1() == locationId){
				//	if( employees[i].getRequest2() !=  NO_LOCATIONS_IN_LIST && locationArray[employees[i].getRequest2()] > 0){ // check whether his request 2 can be satisfied
						locationArray[employees[i].getRequest2()]--;
						locationArray[employees[i].getRequest1()]++;
						employees[i].setAssignedLocation(2);
						//For source employee
						 employees[employeeId].setAssignedLocation(sourceReqId);
			  			  --locationArray[locationId];
			  			if(sourceLocation != -1){  //  Release already assigned one
							++locationArray[sourceLocation]; 
						}
						return true;
				}
	    		
	    		
	    	}
    	}
    	return false;	
	}
	
	public void getMaximumLocation(){
	
		CountingHashMap currentLocs = new CountingHashMap();
		CountingHashMap request1Locs = new CountingHashMap();
	
	/*	for(int i = 0 ; i < locationArray.length ; ++i){
			currentLocs.add(Integer.toString(locationArray[i]));
		}*/
		
		
		 for (int i = 0; i < employees.length; i++) {
			 
			 if(employees[i].getRequest1() != LOCATION_NOT_IN_VACANCY_LIST){	
				 //currentLocs.add(Integer.toString(employees[i].getCurrentLocation()));
				 request1Locs.add(Integer.toString(employees[i].getRequest1()));
			 }
		 }
		 
/*	for (int i = 0; i < currentLocs.keySet().size(); i++) {
		for (int j = 0; j < request1Locs.keySet().size(); j++) {
			if(currentLocs.keySet().)
			
		}
	} */
		 
		 for (String req1 : request1Locs.keySet()) {
			 System.out.println(req1 +" "+ request1Locs.get(req1));
		 }
		 
		 int total =0;
		 for(int i = 0 ; i < locationArray.length ; ++i){
			 for (String req1 : request1Locs.keySet()) {
					if(i == Integer.parseInt(req1)){
						int currentCount = locationArray[i];
						int req1Count =request1Locs.get(req1);
						
						if(currentCount < req1Count){
							total += currentCount;
						}else{
							total += req1Count;
						}						
						
					}
				}
	   	}
		 
	System.out.println(" Theoritical Maximum: "+ total);	 
		 
	}
	
	public void finOldAssignmentScore(){
		
		int request1Count =0;
	 	   int request2Count =0;
	 	   int request3Count =0;
	 	   int currenLocationCount =0;
	 	   int noLocationCount =0;
	 	
	 	   
		 for (int i = 0; i < employeeList.size(); i++) {
			 String request1 = employeeList.get(i).getRequest1().trim();
			 String request2 = employeeList.get(i).getRequest2().trim();
			 String request3 = employeeList.get(i).getRequest3().trim();
			 String currentLocation = employeeList.get(i).getCurrentLocation().trim();
			 String oldAssignment = employeeList.get(i).getOldAssignment().trim();
			 
			 
			 if(!oldAssignment.equals("")  && oldAssignment.equals(request1)){
				 request1Count++;
			 }else if(!oldAssignment.equals("")  && oldAssignment.equals(request2)){
				 request2Count++;
			 }else if(!oldAssignment.equals("")  && oldAssignment.equals(request3)){
				 //System.out.println("EMployee : "+employeeList.get(i).getEmployeeNo()+"   "+ request3);
					request3Count++;
			 }else if(!oldAssignment.equals("")  && oldAssignment.equals(currentLocation) || oldAssignment.equals("")){
				 currenLocationCount++;
			 }else{
				 noLocationCount++;
			 }	 		  
	 	   } 	   
		
	 	   
	 	   
		 int weight =getWeightedEstimation(request1Count,request2Count,request3Count,noLocationCount,currenLocationCount);
	 	   
	 	   System.out.println("Request 1 count: "+ request1Count);
	 	   System.out.println("Request 2 count: "+ request2Count);
	 	   System.out.println("Request 3 count: "+ request3Count);
	 	   System.out.println("Current Location count: "+ currenLocationCount);
	 	   System.out.println("No Location count: "+ noLocationCount);
	 	  System.out.println("Weight is : "+ weight);
	      
		
	}	
}
